using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;

public class TestYooAsset : MonoBehaviour
{
    // Start is called before the first frame update
    string logStr = "";
    string packageName = "MainPackage";
    string packageName2 = "SubPackage";
    string localVersion = "1.0"; 

    void Start()
    {
        Application.logMessageReceived += log;
        YooAssets.Initialize();
        // StartCoroutine(IEInit());
    }

    void log(string logString, string stackTrace, LogType type)
    {
        logStr += logString + "\n";
    }

    void CreatePackage(string pkgName)
    {
        var package = YooAssets.CreatePackage(pkgName);
    }
    
    // private string cdnUrl = $"https://a.unity.cn/client_api/v1/buckets/518accc9-9650-4828-98c2-bf7369494f41/content/YooAsset";
    private string cdnUrl = $"http://127.0.0.1:8900/YooAsset";

    void InitPackage(string pkgName)
    {
        if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
        {
            StartCoroutine(IEInit(package,pkgName));
        }
    }

    IEnumerator IEInit(ResourcePackage package, string pkgName)
    {
        string defaultHostServer = $"{cdnUrl}/StandaloneOSX/{pkgName}";
        string fallbackHostServer = $"{cdnUrl}/StandaloneOSX/{pkgName}";
        IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
        var cacheFileSystemParams = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices);
        var buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();

        var initParameters = new HostPlayModeParameters();
        initParameters.BuildinFileSystemParameters = buildinFileSystemParams;
        initParameters.CacheFileSystemParameters = cacheFileSystemParams;


        var initOperation = package.InitializeAsync(initParameters);
        yield return initOperation;

        if (initOperation.Status == EOperationStatus.Succeed)
            Debug.Log("资源包初始化成功！");
        else
            Debug.LogError($"资源包初始化失败：{initOperation.Error}");


        yield return initOperation;
        // YooAssets.SetDefaultPackage(package);
        
        yield return StartCoroutine(UpdatePackageManifest(package,localVersion));
    }

    IEnumerator UpdatePackageManifest(ResourcePackage package, string version)
    {
        var updateOp = package.UpdatePackageManifestAsync(version);
        yield return updateOp;
        if (updateOp.Status != EOperationStatus.Succeed)
        {
            Debug.Log("更新资源清单的版本信息失败！");
            yield break;
        }
        else
        {
            Debug.Log("更新资源清单的版本信息成功！" + updateOp.Error);
        }
    }

    IEnumerator Download(string pkgName)
    {
        int downloadingMaxNum = 10;
        int failedTryAgain = 3;
        var package = YooAssets.GetPackage(pkgName);
        
        // 2. 请求资源清单的版本信息
        var operation = package.RequestPackageVersionAsync();
        yield return operation;
        if (operation.Status != EOperationStatus.Succeed)
        {
            Debug.Log("请求资源清单的版本信息失败！" + operation.Error);
            yield break;
        }
        else
        {
            Debug.Log("请求资源清单的版本信息成功！" + operation.PackageVersion);
        }

        string newVersion = operation.PackageVersion;
        
        yield return StartCoroutine(UpdatePackageManifest(package, newVersion));
        
            var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);

            //没有需要下载的资源
            if (downloader.TotalDownloadCount == 0)
            {
                yield break;
            }

        //需要下载的文件总数和总大小
        int totalDownloadCount = downloader.TotalDownloadCount;
        long totalDownloadBytes = downloader.TotalDownloadBytes;

        //注册回调方法
        // downloader.DownloadFinishCallback = OnDownloadFinishFunction; //当下载器结束（无论成功或失败）
        // downloader.DownloadErrorCallback = OnDownloadErrorFunction; //当下载器发生错误
        // downloader.DownloadUpdateCallback = OnDownloadUpdateFunction; //当下载进度发生变化
        // downloader.DownloadFileBeginCallback = OnDownloadFileBeginFunction; //当开始下载某个文件
        downloader.DownloadFinishCallback = (data) => { Debug.Log("OnDownloadFinishFunction 下载器结束 " + data.Succeed); };
        downloader.DownloadErrorCallback = (data) => { Debug.Log("DownloadErrorCallback 下载器发生错误 " + data.ErrorInfo); };
        downloader.DownloadUpdateCallback = (data) =>
        {
            Debug.Log("DownloadUpdateCallback 下载进度发生变化  " + data.Progress);
        };
        downloader.DownloadFileBeginCallback = (data) =>
        {
            Debug.Log("DownloadFileBeginCallback 下载某个文件 " + data.FileSize);
        };

            //开启下载
        downloader.BeginDownload();
        yield return downloader;

        //检测下载结果
        if (downloader.Status == EOperationStatus.Succeed)
        {
            //下载成功
            Debug.Log("下载成功");
        }
        else
        {
            //下载失败
            Debug.Log("下载失败");
        }
    }


    IEnumerator DestoryPackage(string pkgName)
    {
        if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
        {
            yield return package.DestroyAsync();
        }
    }
    
    void UnloadAllAssetsPackage(string pkgName)
    {
        if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
        {
            package.UnloadAllAssetsAsync();
        }
    }
    
    void UnloadUnusedAssetsPackage(string pkgName)
    {
        if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
        {
            package.UnloadUnusedAssetsAsync();
        }
    }
    
    IEnumerator CopyBuildInManifest()
    {
        
        yield return null;
    }

    private int count = -5;
    Dictionary<string ,AssetHandle> handleDic = new Dictionary<string , AssetHandle>();

    void CreateObject(ResourcePackage package, string pkgName, string key)
    {
        string keyStr = $"{pkgName}#{key}";
        if (handleDic.TryGetValue(keyStr, out AssetHandle handle))
        {
            InstantiateObject(handle);
        }
        else
        {
            var sync = package.LoadAssetSync<GameObject>(key);
            sync.Completed += sync1 =>
            {
                InstantiateObject(sync1);
            };
            handleDic.Add(keyStr, sync);
        }
    }

    void UnloadObject(ResourcePackage package, string pkgName, string key ,bool release)
    {
        string keyStr = $"{pkgName}#{key}";
        if (handleDic.TryGetValue(keyStr, out AssetHandle handle))
        {
            if (release)
            {
                handle.Release();
                handleDic.Remove(keyStr);
            }
            var assetInfo = handle.GetAssetInfo();
            package.TryUnloadUnusedAsset(assetInfo);
        }
        else
        {
            Debug.LogError("没有找到key");
        }
    }

    void InstantiateObject(AssetHandle handle)
    {
        var obj = handle.AssetObject as GameObject;
        var go = Instantiate(obj).AddComponent<Cube>();
        go.transform.SetParent(Camera.main.transform);
        go.transform.localPosition = new Vector3(count, 0, 20);
        count++;
    }
    
    void CreatePackageBtn(string pkgName)
    {
        GUILayout.BeginHorizontal();
        if (GUILayout.Button($"创建{pkgName}"))
        {
            CreatePackage(pkgName);
        }

        if (GUILayout.Button($"初始化{pkgName}"))
        {
            InitPackage(pkgName);
        }

        if (GUILayout.Button($"更新{pkgName}"))
        {
            StartCoroutine(Download(pkgName));
        }
        if (GUILayout.Button($"卸载{pkgName}"))
        {
            UnloadAllAssetsPackage(pkgName);
        }

        if (GUILayout.Button($"卸载无用{pkgName}"))
        {
            UnloadUnusedAssetsPackage(pkgName);
        }

        if (GUILayout.Button($"Remove{pkgName}"))
        {
            YooAssets.RemovePackage(pkgName);
        }

        if (GUILayout.Button($"销毁{pkgName}"))
        {
            StartCoroutine(DestoryPackage(pkgName));
        }
        GUILayout.EndHorizontal();
        GUILayout.BeginHorizontal();
        if (GUILayout.Button($"{pkgName}创建红色"))
        {
            if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
            {
                var As = package.GetAllAssetInfos();
                string key = "RedCube";
                CreateObject( package, pkgName, key);
            }
        }
        if (GUILayout.Button($"{pkgName}创建蓝色"))
        {
            if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
            {
                string key = "BlueCube";
                CreateObject(package, pkgName, key);
            }
        }
        if (GUILayout.Button($"{pkgName}卸载红色"))
        {
            if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
            {
                var As = package.GetAllAssetInfos();
                string key = "RedCube";
                UnloadObject( package, pkgName, key ,true);
            }
        }
        if (GUILayout.Button($"{pkgName}卸载蓝色"))
        {
            if (YooAssets.TryGetPackage(pkgName) is ResourcePackage package)
            {
                var As = package.GetAllAssetInfos();
                string key = "BlueCube";
                UnloadObject( package, pkgName, key , false);
            }
        }
        GUILayout.EndHorizontal();
    }
    
    private void OnGUI()
    {
        CreatePackageBtn(packageName);
        CreatePackageBtn(packageName2);
        GUILayout.BeginHorizontal();
        if (GUILayout.Button("删除所有方块"))
        {
            // 获取当前游戏对象的所有子节点数量
            int childCount = Camera.main.transform.childCount;

            // 遍历所有子节点并销毁它们
            for (int i = childCount - 1; i >= 0; i--)
            {
                // 获取当前子节点
                Transform child = Camera.main.transform.GetChild(i);

                // 销毁当前子节点
                Destroy(child.gameObject);
            }

            count = -5;
        }

        // if (GUI.Button(new Rect(680, 20, 100, 20), "清除log"))
        if (GUILayout.Button("清除log"))
        {
            logStr = "";
        }

        GUILayout.EndHorizontal();
        GUILayout.BeginScrollView(new Vector2(0, 0));
        GUILayout.Label(logStr);
        GUILayout.EndScrollView();
    }
}

public class RemoteServices : IRemoteServices
{
    private string _defaultHostServer;
    private string _fallbackHostServer;

    public string GetRemoteMainURL(string fileName)
    {
        return $"{_defaultHostServer}/{fileName}";
    }

    public string GetRemoteFallbackURL(string fileName)
    {
        return $"{_fallbackHostServer}/{fileName}";
    }

    public RemoteServices(string defaultHostServer, string fallbackHostServer)
    {
        _defaultHostServer = defaultHostServer;
        _fallbackHostServer = fallbackHostServer;
    }
}